class Controller {
  /**
   * @param {import('koa').Context} ctx 
   * @param {import('../index').Service} service service层
   * @param {string} controllerName 子类名称
   */
  constructor(ctx, service, controllerName) {
    this.ctx = ctx;
    const traceId = this.ctx.traceId;
    this.log = new Proxy(ctx.log, {
      get(target, propKey) {
        return (...args) => {
          target[propKey](`[${ controllerName }] [${ traceId }]`, ...args);
        };
      },
    });
    const cache = {};
    this.service = this.getService(service, cache);
  }

  getService(service, cache) {
    const { ctx, controllerName } = this;
    const self = this;
    return new Proxy(service, {
      get(target, propKey, receiver) {
        const value = Reflect.get(target, propKey, receiver);
        if (typeof value !== 'function') {
          cache[propKey] = {};
          return self.getService(value, cache[propKey]);
        }
        if (!cache[propKey]) {
          cache[propKey] = new value(ctx, controllerName, value.name);
        }
        return cache[propKey];
      },
    });
  }
}

exports.Controller = Controller;